package com.punai.Incomedata.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.punai.Incomedata.bo.ListItemBo;
import com.punai.Incomedata.bo.MonthCzHzTableBo;
import com.punai.Incomedata.service.CztjService;
import com.punai.Incomedata.vo.TabsGetDataVo;
import com.punai.common.core.page.TableDataInfo;
import com.punai.common.utils.DateUtil;
import com.punai.common.utils.NumberUtil;
import com.punai.common.utils.PageUtils;
import com.punai.externalccb.constants.CCBConstants;
import com.punai.externalccb.domain.*;
import com.punai.externalccb.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CztjServiceImpl implements CztjService {

    @Autowired
    private YdTimeMapper ydTimeMapper;
    @Autowired
    private EcoBqitemMapper bqitemMapper;
    @Autowired
    private EcoMeasureitemMapper measureitemMapper;
    @Autowired
    private EcoOtheritemMapper otheritemMapper;
    @Autowired
    private YdBqitemMateMapper ydBqitemMateMapper;
    @Autowired
    private YdczSummaryMapper ydczSummaryMapper;

    @Override
    public TableDataInfo selectTableList(TabsGetDataVo vo) {
        //
        TableDataInfo tableDataInfo = new TableDataInfo();
        String tabType = vo.getTabType();
        String proId = vo.getProId();
        String monthTime = vo.getMonthTime();

        YdTime ydTime = ydTimeMapper.selectOne(
                Wrappers.<YdTime>lambdaQuery()
                        .eq(YdTime::getProId, proId)
                        .eq(YdTime::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                        .eq(YdTime::getOid, monthTime)
        );
        if(ydTime == null) {
           return tableDataInfo;
        }
        Integer ydTimeId = ydTime.getOid();
        Date startdate = ydTime.getStartdate();

        // relType 1 = 分部分项清单  2 = 措施清单  3 = 其他

        if (StrUtil.equals(tabType,"dqcztj")) {
            // 汇总数据
            List<YdczSummary> ydSummaryList = ydczSummaryMapper.selectList(
                    Wrappers.<YdczSummary>lambdaQuery()
                            .eq(YdczSummary::getProId, proId)
                            .eq(YdczSummary::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                            .eq(YdczSummary::getYdDate, monthTime)
                            .eq(YdczSummary::getBidnodeid, 1)
                            .orderBy(true,true,YdczSummary::getOid)
            );
            YdczSummary hj = new YdczSummary();
            hj.setName("合计");
            if (CollUtil.isNotEmpty(ydSummaryList)) {
                BigDecimal total = ydSummaryList.stream().map(YdczSummary::getTotal).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal monthCz = ydSummaryList.stream().map(YdczSummary::getMonthCz).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal costsCz = ydSummaryList.stream().map(YdczSummary::getCostsCz).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                hj.setTotal(total);
                hj.setMonthCz(monthCz);
                hj.setCostsCz(costsCz);
            }
            ydSummaryList.add(hj);

            tableDataInfo.setRows(ydSummaryList);
        }

        if (StrUtil.equals(tabType,"fbfx")) {
            List<YdBqitemMate> ydBqitemMateList = getYdBqitemMates(proId, ydTimeId, 1);
            List<Integer> bqitemids = ydBqitemMateList.stream().map(YdBqitemMate::getBqitemid).collect(Collectors.toList());

            List<YdTime> ydTimes = ydTimeMapper.selectList(Wrappers.<YdTime>lambdaQuery()
                    .le(YdTime::getStartdate, startdate)
            );
            List<Integer> timeIds = ydTimes.stream().map(YdTime::getOid).filter(Objects::nonNull).collect(Collectors.toList());
            List<YdBqitemMate> bqitemMateList = getYdBqitemMatesList(proId, timeIds, 1);

            PageUtils.startPage();
            List<EcoBqitem> ecoBqitems = bqitemMapper.selectList(
                    Wrappers.<EcoBqitem>lambdaQuery()
                            .eq(EcoBqitem::getProId, proId)
                            .eq(EcoBqitem::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                            .eq(EcoBqitem::getItemtype,2)
                            .in(EcoBqitem::getBqitemid,bqitemids)
                            .orderBy(true,true,EcoBqitem::getCode)
            );

            Map<Integer, YdBqitemMate> bqitemMap = ydBqitemMateList.stream().collect(Collectors.toMap(YdBqitemMate::getBqitemid, Function.identity(), (key1, key2) -> key2));
            Map<Integer, List<YdBqitemMate>> bqitemLeMap = bqitemMateList.stream().filter(v -> v.getBqitemid() != null).collect(Collectors.groupingBy(YdBqitemMate::getBqitemid, Collectors.toList()));
            List<ListItemBo> listItemBos = new ArrayList<>();
            for (EcoBqitem in : ecoBqitems) {
                ListItemBo out = new ListItemBo();
                out.setId(in.getId());
                out.setCode(in.getCode());
                out.setName(in.getDescription());
                out.setUnit(in.getUnit());
                out.setSpec(in.getSpec());
                out.setYsgcl(in.getQuantity());
                out.setYsdj(in.getRate());
                out.setYshj(NumberUtil.multiply(out.getYsgcl(),out.getYsdj()));
                YdBqitemMate ydBqitemMate = bqitemMap.get(in.getBqitemid());
                out.setMonthGcl(ydBqitemMate.getMonthamout());
                out.setMonthCz(ydBqitemMate.getMonthcz());
                out.setMonthWcl(ydBqitemMate.getMonthwcl());
                List<YdBqitemMate> mate = bqitemLeMap.get(in.getBqitemid());
                BigDecimal klgcl = mate.stream().map(YdBqitemMate::getMonthamout).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                out.setKlGcl(klgcl);
                out.setKlCz(mate.stream().map(YdBqitemMate::getMonthcz).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
                BigDecimal divide = NumberUtil.divide(klgcl, in.getQuantity());
                out.setKlWcl(NumberUtil.multiply(divide,new BigDecimal(100)));
                listItemBos.add(out);
            }

            PageInfo<EcoBqitem> pageInfo = new PageInfo<>(ecoBqitems);
            tableDataInfo.setTotal(pageInfo.getTotal());
            tableDataInfo.setRows(listItemBos);
        } else if (StrUtil.equals(tabType,"csxm")) {

            List<YdBqitemMate> ydBqitemMateList = getYdBqitemMates(proId, ydTimeId, 2);
            List<Integer> bqitemids = ydBqitemMateList.stream().map(YdBqitemMate::getBqitemid).collect(Collectors.toList());

            List<YdTime> ydTimes = ydTimeMapper.selectList(Wrappers.<YdTime>lambdaQuery()
                    .le(YdTime::getStartdate, startdate)
            );
            List<Integer> timeIds = ydTimes.stream().map(YdTime::getOid).filter(Objects::nonNull).collect(Collectors.toList());
            List<YdBqitemMate> bqitemMateList = getYdBqitemMatesList(proId, timeIds, 2);

            PageUtils.startPage();
            List<EcoMeasureitem> measureitems = measureitemMapper.selectList(
                    Wrappers.<EcoMeasureitem>lambdaQuery()
                            .eq(EcoMeasureitem::getProId, proId)
                            .eq(EcoMeasureitem::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                            .in(EcoMeasureitem::getMeasureitemid,bqitemids)
                            .eq(EcoMeasureitem::getItemtype,2)
                            .orderBy(true,true,EcoMeasureitem::getCode)
            );
            Map<Integer, YdBqitemMate> bqitemMap = ydBqitemMateList.stream().collect(Collectors.toMap(YdBqitemMate::getBqitemid, Function.identity(), (key1, key2) -> key2));
            Map<Integer, List<YdBqitemMate>> bqitemLeMap = bqitemMateList.stream().filter(v -> v.getBqitemid() != null).collect(Collectors.groupingBy(YdBqitemMate::getBqitemid, Collectors.toList()));
            List<ListItemBo> listItemBos = new ArrayList<>();
            for (EcoMeasureitem in : measureitems) {
                ListItemBo out = new ListItemBo();
                out.setId(in.getId());
                out.setCode(in.getCode());
                out.setName(in.getDescription());
                out.setUnit(in.getUnit());
                out.setSpec(in.getSpec());
                out.setYsgcl(in.getQuantity());
                out.setYsdj(in.getRate());
                out.setYshj(NumberUtil.multiply(out.getYsgcl(),out.getYsdj()));
                YdBqitemMate ydBqitemMate = bqitemMap.get(in.getMeasureitemid());
                out.setMonthGcl(ydBqitemMate.getMonthamout());
                out.setMonthCz(ydBqitemMate.getMonthcz());
                out.setMonthWcl(ydBqitemMate.getMonthwcl());
                List<YdBqitemMate> mate = bqitemLeMap.get(in.getMeasureitemid());
                BigDecimal klgcl = mate.stream().map(YdBqitemMate::getMonthamout).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                out.setKlGcl(klgcl);
                out.setKlCz(mate.stream().map(YdBqitemMate::getMonthcz).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
                BigDecimal divide = NumberUtil.divide(klgcl, in.getQuantity());
                out.setKlWcl(NumberUtil.multiply(divide,new BigDecimal(100)));
                listItemBos.add(out);
            }

            PageInfo<EcoMeasureitem> pageInfo = new PageInfo<>(measureitems);
            tableDataInfo.setTotal(pageInfo.getTotal());
            tableDataInfo.setRows(listItemBos);

        } else if (StrUtil.equals(tabType,"qtxm")) {
            List<YdBqitemMate> ydBqitemMateList = getYdBqitemMates(proId, ydTimeId, 3);
            List<Integer> bqitemids = ydBqitemMateList.stream().map(YdBqitemMate::getBqitemid).collect(Collectors.toList());
            PageUtils.startPage();
            List<EcoOtheritem> ecoOtheritems = otheritemMapper.selectList(
                    Wrappers.<EcoOtheritem>lambdaQuery()
                            .eq(EcoOtheritem::getProId, proId)
                            .eq(EcoOtheritem::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                            .in(EcoOtheritem::getOid,bqitemids)
                            .orderBy(true,true,EcoOtheritem::getOid)
            );

            Map<Integer, YdBqitemMate> bqitemMap = ydBqitemMateList.stream().collect(Collectors.toMap(YdBqitemMate::getBqitemid, Function.identity(), (key1, key2) -> key2));
            List<ListItemBo> listItemBos = new ArrayList<>();
            for (EcoOtheritem in : ecoOtheritems) {
                ListItemBo out = new ListItemBo();
                out.setId(in.getId());
                out.setCode(in.getOrdcode());
                out.setName(in.getName());
                out.setUnit(in.getUnit());
                out.setYsgcl(in.getQuantity());
                out.setYsdj(in.getRate());
                out.setYshj(NumberUtil.multiply(out.getYsgcl(),out.getYsdj()));
                YdBqitemMate ydBqitemMate = bqitemMap.get(in.getOid());
                out.setMonthGcl(ydBqitemMate.getMonthgcl());
                out.setMonthCz(ydBqitemMate.getMonthcz());
                out.setMonthWcl(ydBqitemMate.getMonthwcl());
                out.setKlGcl(ydBqitemMate.getCostsamout());
                out.setKlCz(ydBqitemMate.getCostscz());
                out.setKlWcl(ydBqitemMate.getCostswcl());
                listItemBos.add(out);
            }

            PageInfo<EcoOtheritem> pageInfo = new PageInfo<>(ecoOtheritems);
            tableDataInfo.setTotal(pageInfo.getTotal());
            tableDataInfo.setRows(listItemBos);
        }

        return tableDataInfo;
    }

    private List<YdBqitemMate> getYdBqitemMates(String proId, Integer id, int val) {
        return ydBqitemMateMapper.selectList(
                Wrappers.<YdBqitemMate>lambdaQuery()
                        .eq(YdBqitemMate::getProId, proId)
                        .eq(YdBqitemMate::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                        .eq(YdBqitemMate::getYddate, id)
                        .eq(YdBqitemMate::getReltype, val)
                        .orderByAsc(YdBqitemMate::getOid)
        );
    }

    private List<YdBqitemMate> getYdBqitemMatesList(String proId, List<Integer> id, int val) {
        return ydBqitemMateMapper.selectList(
                Wrappers.<YdBqitemMate>lambdaQuery()
                        .eq(YdBqitemMate::getProId, proId)
                        .eq(YdBqitemMate::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                        .in(YdBqitemMate::getYddate, id)
                        .eq(YdBqitemMate::getReltype, val)
                        .orderByAsc(YdBqitemMate::getOid)
        );
    }

    @Override
    public List<MonthCzHzTableBo> selectHzData(TabsGetDataVo vo) {
        String startTime = vo.getStartTime();
        String endTime = vo.getEndTime();
        String proId = vo.getProId();
        // 当前项目的
        List<YdTime> ydTimes = ydTimeMapper.selectList(
                Wrappers.<YdTime>lambdaQuery()
                        .eq(YdTime::getProId, proId)
                        .eq(YdTime::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                        .orderByAsc(YdTime::getStartdate)
        );

        if (CollUtil.isEmpty(ydTimes)) {
            return null;
        }

        // 取汇总表   但是汇总表工具方还没加
        // 格式  序号	期次	当期除税产值	当期含税产值	开累除税产值	开累含税产值

        List<Integer> ydTimeIds = ydTimes.stream().map(YdTime::getOid).collect(Collectors.toList());

        List<YdczSummary> ydSummaryList = ydczSummaryMapper.selectList(
                Wrappers.<YdczSummary>lambdaQuery()
                        .eq(YdczSummary::getProId, proId)
                        .eq(YdczSummary::getStagetype, CCBConstants.CCB_TYPE.YDCBFX.getCode())
                        .in(YdczSummary::getYdDate, ydTimeIds)
        );
        Map<Integer, List<YdczSummary>> collect = ydSummaryList.stream().collect(Collectors.groupingBy(YdczSummary::getYdDate));

        List<MonthCzHzTableBo> result = new ArrayList<>();
        int xh = 0;
        for (YdTime ydTime : ydTimes) {

            String dateToyM = DateUtil.dateToyM(ydTime.getStartdate());
            if(StrUtil.compare(dateToyM,startTime,true) < 0 || StrUtil.compare(dateToyM, endTime, true) > 0) continue;

            xh++;
            Integer oid = ydTime.getOid();
            List<YdczSummary> ydSummaryList1 = collect.get(oid);

            MonthCzHzTableBo bo = new MonthCzHzTableBo();
            bo.setXh(xh);
            bo.setQcId(oid);
            bo.setQcName(dateToyM);
            if (CollUtil.isNotEmpty(ydSummaryList1)) {
                BigDecimal notTaxTotal = ydSummaryList1.stream().filter(e -> !StrUtil.equals(e.getName(), "税金")).map(YdczSummary::getMonthCz).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal inTaxTotal = ydSummaryList1.stream().map(YdczSummary::getMonthCz).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal notTaxCostTotal = ydSummaryList1.stream().filter(e -> !StrUtil.equals(e.getName(), "税金")).map(YdczSummary::getCostsCz).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal inTaxCostTotal = ydSummaryList1.stream().map(YdczSummary::getCostsCz).reduce(BigDecimal.ZERO, BigDecimal::add);
                bo.setMonthNoTaxCz(notTaxTotal);
                bo.setMonthTaxCz(inTaxTotal);
                bo.setCostsNoTaxCz(notTaxCostTotal);
                bo.setCostsTaxCz(inTaxCostTotal);
            }
            result.add(bo);
        }
        return result;
    }
}
